package com.androidvizlab.bachelor.Views;

import com.androidvizlab.bachelor.R;
import com.androidvizlab.bachelor.customcomponents.fragments.EditOptionFileFragment;
import com.androidvizlab.bachelor.customcomponents.listenersandadapters.CustomTextChangedListener;
import com.androidvizlab.bachelor.datamodels.OptionsFileModel;
import com.androidvizlab.bachelor.datamodels.OptionsFile.RunType;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;

/**
 * This represents the View in the MVC pattern used in the EditOptionFileActivity.
 * Holds reference to the Views of the EditOptionFileActivity. This class provides
 * methods for retrieving and setting values from/to the Views that are inflated in the Activity
 * @author TheHive
 */
public class EditOptionFileView {
	
	private Activity activity = null;
	
	//Layouts
	//Variables used to hide and show EditText for the calibration file path.
	private LinearLayout containerCal = null;
	private LinearLayout containerProd = null;
	private LinearLayout containerImgFileInput = null;
	private LinearLayout containerHelpFile = null;
	private LinearLayout containerPtsDetection = null;
	
	//EditText
	//General
	private EditText etFilePathProduction = null;
	private EditText etFilePathCalibration = null;
	private EditText etTriggingInterval = null;
	private EditText etNrCameras = null;
	private EditText etNrTimePts = null;
	private EditText etNrMarkers = null;
	private EditText etApprxFrameMarkerLimit = null;
	
	//Advanced
	private EditText etPtsDetectionOffsetPx = null;
	private EditText etPtsDetectionMinPx = null;
	private EditText etPtsDetectionMaxPx = null;
	private EditText etMinsep = null;
	private EditText etMaxErr = null;
	
	//RadioGroup and RadioButton
	
	/*
	 * Parent view containing two RadioButton with custom images.
	 * 	Toggle between the general option(tab) and the advanced option(tab)
	 */
	private RadioGroup rgSwitchOptionFragment = null;
	
	private RadioGroup rgImgFileInput = null;
	
	private RadioGroup rgImgFileOutput = null;
	
	//Buttons
	private Button btnSend = null; //when pressed, sends the data to the server via socket connection.
	private Button btnReset = null; //when pressed, reset the optionfile data to default
		
	//Listener
	private OnClickListener onClickListener = null;
	private OnCheckedChangeListener onCheckedChangeListener = null;
	private OnItemClickListener onItemClickListener = null;
	
	//TextWatcher - EditText validation
	private CustomTextChangedListener customTextChangedListener = null;
	
	//Fragment related
	private FragmentManager fragmentManager = null;
	private FragmentTransaction fragmentTransaction = null;
	private EditOptionFileFragment fragmentEditGeneral = null;
	private EditOptionFileFragment fragmentEditAdvanced = null;
	
	//FRAGMENT TAGS
	public static final String OPTIONSFILE_FRAGMENT_GENERAL = "general_frag";
	public static final String OPTIONSFILE_FRAGMENT_ADVANCED = "advanced_frag";	
	
	//Bundles and fragment argument
	private Bundle extraInfo = null;
	
	public EditOptionFileView()
	{}
	
	public EditOptionFileView(Activity activity)
	{
		this.activity = activity;
	}
	
	/**
	 * Initialise Button,EditText and radio buttons 
	 */	
	public void initUIComponents()
	{		
		//INSTANTIATE OPTIONS FRAGMENT(GENERAL AND ADVANCED)
		//initCustomFragments(); //Initialises fragments and fragment components
		
		//LinearLayout
		containerCal = (LinearLayout) activity.findViewById(R.id.layoutCalibrationFilePath);
		containerProd = (LinearLayout) activity.findViewById(R.id.layoutProductionFilePath);
		containerHelpFile = (LinearLayout) activity.findViewById(R.id.containerHelpFile);
		containerPtsDetection = (LinearLayout) activity.findViewById(R.id.containerPointDetection);
		
		//EditText 
		etFilePathProduction = (EditText) activity.findViewById(R.id.etFilePathProduction);
		etFilePathCalibration = (EditText) activity.findViewById(R.id.etFilePathCalibration);
		etTriggingInterval = (EditText) activity.findViewById(R.id.etTriggingInterval);
		etNrCameras = (EditText) activity.findViewById(R.id.etNrCameras);
		etNrTimePts = (EditText) activity.findViewById(R.id.etNrTimePts);
		etNrMarkers = (EditText) activity.findViewById(R.id.etNrMarkers);
		//etApprxFrameMarkerLimit = (EditText) activity.findViewById(R.id.etApprxFrameMarkerLimit);
		
		//RadioGroup and RadioButton
		rgSwitchOptionFragment = (RadioGroup) activity.findViewById(R.id.rgSwitchFragment); 
		
		//Buttons
		btnReset = (Button) activity.findViewById(R.id.btnReset);
		btnSend = (Button) activity.findViewById(R.id.btnSend);
		
		//Buttons: Add listener
		rgSwitchOptionFragment.setOnCheckedChangeListener(onCheckedChangeListener);
		btnSend.setOnClickListener(onClickListener);
		btnReset.setOnClickListener(onClickListener);
	}
	
	//*** INITIALISE FRAGMENT ***//
	/**
	 * Initialises two fragments that represents the option file.
	 * These two fragments represents, a general and an advanced option.
	 */
	public void initCustomFragments()
	{
		//EDIT SETTINGS(OPTIONS-file) GENERAL
		fragmentEditGeneral = new EditOptionFileFragment();
		
		//Add listener to the inflated View(Button, CheckBoxes, RadioButtons, EditText. etc..)
		fragmentEditGeneral.setOnClickListener(onClickListener); //pass an OnClickListener
		fragmentEditGeneral.setOnCheckedChangeListener(onCheckedChangeListener); //pass an OnCheckedChangeListener
		fragmentEditGeneral.setTextWatcher(customTextChangedListener); //pass a TextWatcher(TextChanedListener)
		
		//Pass the id of the xml file to inflate
		extraInfo = new Bundle();
		extraInfo.putInt("layoutid", R.layout.editsettingsgeneral);
		
		fragmentEditGeneral.setArguments(extraInfo);
		
		fragmentTransaction = fragmentManager.beginTransaction();
		
		fragmentTransaction.add(R.id.fragmentHolder, fragmentEditGeneral, OPTIONSFILE_FRAGMENT_GENERAL);
		fragmentTransaction.addToBackStack(null);
		
		//EDIT SETTINGS(OPTIONS-file) ADVANCED
		fragmentEditAdvanced = new EditOptionFileFragment();
		
		//Add listener to the inflated View(Button, CheckBoxes, RadioButtons, EditText. etc..)
		fragmentEditAdvanced.setOnClickListener(onClickListener); //pass an OnClickListener
		fragmentEditAdvanced.setOnCheckedChangeListener(onCheckedChangeListener); //pass an OnCheckedChangeListener
		fragmentEditAdvanced.setTextWatcher(customTextChangedListener); //pass a TextWatcher(TextChanedListener)
		
		//Pass the id of the xml file to inflate
		extraInfo = new Bundle();
		extraInfo.putInt("layoutid", R.layout.editsettingsadvanced);
		
		fragmentEditAdvanced.setArguments(extraInfo);
		
		fragmentTransaction.add(R.id.fragmentHolder, fragmentEditAdvanced, OPTIONSFILE_FRAGMENT_ADVANCED);
		fragmentTransaction.addToBackStack(null);
		
		//hide the second fragment until the advanced button is clicked
		fragmentTransaction.hide(fragmentEditAdvanced);
		fragmentTransaction.commit();
	}
	
	//*** SWITCH BETWEEN THE GENERAL AND ADVANCED OPTION ***//
	
	/**
	 * Show/hide fragment by a given id
	 * @param sourceId Id of the event source
	 */
	public void switchFragment(int sourceId)
	{
		switch(sourceId)
		{
		case R.id.rbGeneral:
			showFragment(EditOptionFileView.OPTIONSFILE_FRAGMENT_GENERAL);
			hideFragment(EditOptionFileView.OPTIONSFILE_FRAGMENT_ADVANCED);
			break;
			
		case R.id.rbAdvanced:
			showFragment(EditOptionFileView.OPTIONSFILE_FRAGMENT_ADVANCED);
			hideFragment(EditOptionFileView.OPTIONSFILE_FRAGMENT_GENERAL);
			break;
		}
	}
	
	/**
	 * Make the fragment by a given tag visible
	 * 
	 * @param tag associated with a fragment
	 */
	public void showFragment(String tag)
	{
		Fragment fragment = fragmentManager.findFragmentByTag(tag);
		
		fragmentTransaction = fragmentManager.beginTransaction();
		
		fragmentTransaction.show(fragment);
		
		fragmentTransaction.commit();
	}
	
	/**
	 * Make the fragment by a given tag hidden
	 * 
	 * @param tag associated with a fragment
	 */
	public void hideFragment(String tag)
	{
		Fragment fragment = fragmentManager.findFragmentByTag(tag);
		
		fragmentTransaction = fragmentManager.beginTransaction();
		
		fragmentTransaction.hide(fragment);
		
		fragmentTransaction.commit();
	}
	
	/**
	 * Hides/Shows EditText for calibration file path or production file path 
	 * 
	 * @param runType Specify the run type in the option file, Calibration,
	 * Production or Recalculation.
	 */
	public void showRunTypePathContainer(RunType runType)
	{
		if(containerCal == null || containerProd == null)
		{
			containerCal = (LinearLayout) activity.findViewById(R.id.layoutCalibrationFilePath);
			containerProd = (LinearLayout) activity.findViewById(R.id.layoutProductionFilePath);
		}
		
		if(runType == OptionsFileModel.RunType.CALIBRATION)
		{
			containerCal.setVisibility(View.VISIBLE);
			containerProd.setVisibility(View.GONE);
		}
		else if(runType == OptionsFileModel.RunType.PRODUCTION)
		{
			containerCal.setVisibility(View.GONE);
			containerProd.setVisibility(View.VISIBLE);
		}	
	}
	
	/**
	 * Show/hide Point Detection options(Form)
	 */
	public void showPointDetectionOpts()
	{
		if(containerPtsDetection == null)
		{
			containerPtsDetection = (LinearLayout) activity.findViewById(R.id.containerPointDetection);
		}
		
		if(containerPtsDetection.getVisibility() == View.GONE)
		{
			containerPtsDetection.setVisibility(View.VISIBLE);
		}
		else
		{
			containerPtsDetection.setVisibility(View.GONE);
		}
	}
	
	/**
	 * Show/hide Image File input options(Form)
	 */
	public void showImageFileInOpts()
	{
		/*
		if(rgImgFileInput == null)
		{
			rgImgFileInput = (RadioGroup) activity.findViewById(R.id.rgImgFileInput);
		}
		
		if(rgImgFileInput.getVisibility() == View.GONE)
		{
			rgImgFileInput.setVisibility(View.VISIBLE);
		}
		else
		{
			rgImgFileInput.setVisibility(View.GONE);
		}*/
		
		if(containerImgFileInput == null)
		{
			containerImgFileInput = (LinearLayout) activity.findViewById(R.id.containerImgFileInput);
		}
		
		if(containerImgFileInput.getVisibility() == View.GONE)
		{
			containerImgFileInput.setVisibility(View.VISIBLE);
		}
		else
		{
			containerImgFileInput.setVisibility(View.GONE);
		}
	}
	
	/**
	 * Show/hide Image File output options(Form)
	 */
	public void showImageFileOutOpts()
	{
		if(rgImgFileOutput == null)
		{
			rgImgFileOutput = (RadioGroup) activity.findViewById(R.id.rgImgFileOutput);
		}
		
		if(rgImgFileOutput.getVisibility() == View.GONE)
		{
			rgImgFileOutput.setVisibility(View.VISIBLE);
		}
		else
		{
			rgImgFileOutput.setVisibility(View.GONE);
		}
	}
	
	/**
	 * Show/hide help file options(CheckBoxes)
	 */
	public void showHelpFileOptions()
	{
		if(containerHelpFile == null)
		{
			containerHelpFile = (LinearLayout) activity.findViewById(R.id.containerHelpFile);
		}
		
		if(containerHelpFile.getVisibility() == View.GONE)
		{
			containerHelpFile.setVisibility(View.VISIBLE);
		}
		else
		{
			containerHelpFile.setVisibility(View.GONE);
		}
	}
	
	//*** SET TEXT ***//
	
	//*** ADD AND SUBTRACT CAMERA GROUP ***//
	
	/**
	 * Set Number of Triplet Camera Group
	 * @param input the value to be displayed
	 */
	public void setNumTriCameraGroup(String input)
	{
		if(etNrCameras == null)
		{
			etNrCameras = (EditText) activity.findViewById(R.id.etNrCameras);
			Log.i("ui_null","ET nr cameras was null");
		}
		etNrCameras.setText(input);
	}
	
	/**
	 * Set Trigging interval
	 * @param input the value to be displayed
	 */
	public void setTriggingInterval(String input)
	{
		if(etTriggingInterval == null)
		{
			etTriggingInterval = (EditText) activity.findViewById(R.id.etTriggingInterval);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		etTriggingInterval.setText(input);
	}
	
	/**
	 * Set Number of Time points
	 * @param input the value to be displayed
	 */
	public void setTimePts(String input)
	{
		if(etNrTimePts == null)
		{
			etNrTimePts = (EditText) activity.findViewById(R.id.etNrTimePts);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		etNrTimePts.setText(input);
	}
	
	/**
	 * Set Number of Markers
	 * @param input the value to be displayed
	 */
	public void setNumMarkers(String input)
	{
		if(etNrMarkers == null)
		{
			etNrMarkers = (EditText) activity.findViewById(R.id.etNrMarkers);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		etNrMarkers.setText(input);
	}
	
	/**
	 * Set Calibration file path
	 * @param input the value to be displayed
	 */
	public void setCalibrationFilePath(String input)
	{
		if(etFilePathCalibration == null)
		{
			etFilePathCalibration = (EditText) activity.findViewById(R.id.etFilePathCalibration);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		etFilePathCalibration.setText(input);
	}
	
	/**
	 * Set Production file path
	 * @param input the value to be displayed
	 */
	public void setProductionFilePath(String input)
	{
		if(etFilePathProduction == null)
		{
			etFilePathProduction = (EditText) activity.findViewById(R.id.etFilePathProduction);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		etFilePathProduction.setText(input);
	}
	
	//Set Approximate Frame Marker Limit
	/*public void setApproxFrameMarkerLimit(String input)
	{
		if(etApprxFrameMarkerLimit == null)
		{
			etApprxFrameMarkerLimit = (EditText) activity.findViewById(R.id.etApprxFrameMarkerLimit);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		etApprxFrameMarkerLimit.setText(input);
	}*/
	
	/**
	 * Set Point Detection offset pixel
	 * @param input the value to be displayed
	 */
	public void setPtsDetectionOffsetPixel(String input)
	{
		if(etPtsDetectionOffsetPx == null)
		{
			etPtsDetectionOffsetPx = (EditText) activity.findViewById(R.id.etPtsDetectionOffsetPx);
		}
		
		etPtsDetectionOffsetPx.setText(input);
	}
	
	/**
	 * Set Point Detection Min. pixel
	 * @param input the value to be displayed
	 */
	public void setPtsDetectionMinPixel(String input)
	{
		if(etPtsDetectionMinPx == null)
		{
			etPtsDetectionMinPx = (EditText) activity.findViewById(R.id.etPtsDetectionMinPx);
		}
		
		etPtsDetectionMinPx.setText(input);
	}
	
	/**
	 * Set Point Detection Max. pixel
	 * @param input the value to be displayed
	 */
	public void setPtsDetectionMaxPixel(String input)
	{
		if(etPtsDetectionMaxPx == null)
		{
			etPtsDetectionMaxPx = (EditText) activity.findViewById(R.id.etPtsDetectionMaxPx);
		}
		
		etPtsDetectionMaxPx.setText(input);
	}
	
	/**
	 * Set Point Detection offset pixel
	 * @param input the value to be displayed
	 */
	public void setMinSep(String input)
	{
		if(etMinsep == null)
		{
			etMinsep = (EditText) activity.findViewById(R.id.etMinsep);
		}
		
		etMinsep.setText(input);
	}
	
	/**
	 * Set Point Detection offset pixel
	 * @param input the value to be displayed
	 */
	public void setMaxError(String input)
	{
		if(etMaxErr == null)
		{
			etMaxErr = (EditText) activity.findViewById(R.id.etMaxErr);
		}
		
		etMaxErr.setText(input);
	}
	
	//*** GET TEXT ***//
	
	/**
	 * Get Number of Triplet Camera Group
	 * @return
	 */
	public String getNumTriCameraGroup()
	{
		if(etNrCameras == null)
		{
			etNrCameras = (EditText) activity.findViewById(R.id.etNrCameras);
			Log.i("ui_null","ET nr cameras was null");
		}
		return etNrCameras.getText().toString().trim();
	}
	
	//Get Trigging interval
	public String getTriggingInterval()
	{
		if(etTriggingInterval == null)
		{
			etTriggingInterval = (EditText) activity.findViewById(R.id.etTriggingInterval);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		return etTriggingInterval.getText().toString().trim();
	}
	
	//Get Number of Time points
	public String getNumTimePts()
	{
		if(etNrTimePts == null)
		{
			etNrTimePts = (EditText) activity.findViewById(R.id.etNrTimePts);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		return etNrTimePts.getText().toString().trim();
	}
	
	//Get Number of Markers
	public String getNumMarkers()
	{
		if(etNrMarkers == null)
		{
			etNrMarkers = (EditText) activity.findViewById(R.id.etNrMarkers);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		return etNrMarkers.getText().toString().trim();
	}
	
	//Get Calibration file path
	public String getCalibrationFilePath()
	{
		if(etFilePathCalibration == null)
		{
			etFilePathCalibration = (EditText) activity.findViewById(R.id.etFilePathCalibration);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		return etFilePathCalibration.getText().toString().trim();
	}
	
	//Get Production file path
	public String getProductionFilePath()
	{
		if(etFilePathProduction == null)
		{
			etFilePathProduction = (EditText) activity.findViewById(R.id.etFilePathProduction);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		return etFilePathProduction.getText().toString().trim();
	}
	
	//Get Approximate Frame Marker Limit
	/*public String getApproxFrameMarkerLimit()
	{
		if(etApprxFrameMarkerLimit == null)
		{
			etApprxFrameMarkerLimit = (EditText) activity.findViewById(R.id.etApprxFrameMarkerLimit);
			Log.i("ui_null","ET nr cameras was null");
		}
		
		return etApprxFrameMarkerLimit.getText().toString().trim();
	}*/
	
	//Get Point Detection offset pixel
	public String getPtsDetectionOffsetPixel()
	{
		if(etPtsDetectionOffsetPx == null)
		{
			etPtsDetectionOffsetPx = (EditText) activity.findViewById(R.id.etPtsDetectionOffsetPx);
		}
		
		return etPtsDetectionOffsetPx.getText().toString().trim();
	}
	
	//Get Point Detection Min. pixel
	public String getPtsDetectionMinPixel()
	{
		if(etPtsDetectionMinPx == null)
		{
			etPtsDetectionMinPx = (EditText) activity.findViewById(R.id.etPtsDetectionMinPx);
		}
		
		return etPtsDetectionMinPx.getText().toString().trim();
	}
	
	//Get Point Detection Max. pixel
	public String getPtsDetectionMaxPixel()
	{
		if(etPtsDetectionMaxPx == null)
		{
			etPtsDetectionMaxPx = (EditText) activity.findViewById(R.id.etPtsDetectionMaxPx);
		}
		
		return etPtsDetectionMaxPx.getText().toString().trim();
	}
	
	//Get Point Detection offset pixel
	public String getMinSep()
	{
		if(etMinsep == null)
		{
			etMinsep = (EditText) activity.findViewById(R.id.etMinsep);
		}
		
		return etMinsep.getText().toString().trim();
	}
	
	//Get Point Detection offset pixel
	public String getMaxError()
	{
		if(etMaxErr == null)
		{
			etMaxErr = (EditText) activity.findViewById(R.id.etMaxErr);
		}
		
		return etMaxErr.getText().toString().trim();
	}
	
	/**
	 * Helper method: sets checked on the given checkbox by id
	 * @param id identifier for the given CheckBox.
	 * @param value the boolean value to be set on the setChecked(boolean)-method.
	 */
	public void setCheckBoxValue(int id,boolean value)
	{
		CheckBox cb = (CheckBox) activity.findViewById(id);
		cb.setChecked(value);
	}
	
	/**
	 * Selects RadioButton given by id.
	 * @param id identifier for the given RadioButton.
	 * @param value the boolean that determines if the RadioButton is selected.
	 */
	public void selectRadioButton(int id, boolean value)
	{
		RadioButton rb = (RadioButton) activity.findViewById(id);
		rb.setSelected(value);
	}
	
	public void setErrorFieldError(int id, String msg)
	{
		switch(id)
		{
		case R.id.etFilePathCalibration:
			
			this.etFilePathCalibration.setError(msg);
			
			break;
		
		case R.id.etFilePathProduction:
			
			this.etFilePathProduction.setError(msg);
			
			break;
			
		case R.id.etTriggingInterval:
			
			this.etTriggingInterval.setError(msg);
			
			break;
			
		case R.id.etNrCameras:
			
			this.etNrCameras.setError(msg);
			
			break;
			
		case R.id.etNrTimePts:
			
			this.etNrTimePts.setError(msg);
			
			break;
			
		case R.id.etNrMarkers:
			
			this.etNrMarkers.setError(msg);
			
			break;
			
		case R.id.etPtsDetectionMinPx:
			
			this.etPtsDetectionMinPx.setError(msg);
			
			break;
			
		case R.id.etPtsDetectionMaxPx:
			
			this.etPtsDetectionMaxPx.setError(msg);
			
			break;
			
		case R.id.etPtsDetectionOffsetPx:
			
			this.etPtsDetectionOffsetPx.setError(msg);
			
			break;
			
		case R.id.etMinsep:
			
			this.etMinsep.setError(msg);
			
			break;
			
		case R.id.etMaxErr:
			
			this.etMaxErr.setError(msg);
			
			break;
		}
	}
	
	//*** GETTERS AND SETTERS ***//
	
	public Activity getActivity() {
		return activity;
	}

	public void setActivity(Activity activity) {
		this.activity = activity;
	}

	public OnClickListener getOnClickListener() {
		return onClickListener;
	}

	public void setOnClickListener(OnClickListener onClickListener) {
		this.onClickListener = onClickListener;
	}

	public OnCheckedChangeListener getOnCheckedListener() {
		return onCheckedChangeListener;
	}

	public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
		this.onCheckedChangeListener = onCheckedChangeListener;
	}

	public OnItemClickListener getOnItemClickListener() {
		return onItemClickListener;
	}

	public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
		this.onItemClickListener = onItemClickListener;
	}

	public FragmentManager getFragmentManager() {
		return fragmentManager;
	}

	public void setFragmentManager(FragmentManager fragmentManager) {
		this.fragmentManager = fragmentManager;
	}

	public FragmentTransaction getFragmentTransaction() {
		return fragmentTransaction;
	}

	public void setFragmentTransaction(FragmentTransaction fragmentTransaction) {
		this.fragmentTransaction = fragmentTransaction;
	}

	public CustomTextChangedListener getCustomTextChangedListener() {
		return customTextChangedListener;
	}

	public void setCustomTextChangedListener(
			CustomTextChangedListener customTextChangedListener) {
		this.customTextChangedListener = customTextChangedListener;
	}
}
